#include "lib.h"

void list_init(struct List* list){
    list->prev = list;
    list->next = list;
}

void list_add_to_behind(struct List* entry,struct List* newEntry){
    newEntry->next = entry->next;
    newEntry->prev = entry;
    newEntry->next->prev = newEntry;
    entry->next = newEntry;
}

void list_add_to_before(struct List* entry,struct List* newEntry){
    newEntry->next = entry;
    newEntry->prev = entry->prev;
    entry->prev->next = newEntry;
    entry->prev = newEntry;
}

void list_del(struct List* entry){
    entry->next->prev = entry->prev;
    entry->prev->next = entry->next;
}

long list_is_empty(struct List* entry){
    if(entry == entry->next && entry->prev == entry)
        return 1;
    else
        return 0;
}

struct List* list_prev(struct List* entry){
    if(entry->prev != NULL){
        return entry->prev;
    }else{
        return NULL;
    }
}

struct List* list_next(struct List* entry){
    if(entry->prev != NULL){
        return entry->prev;
    }else{
        return NULL;
    }
}

/*
asm(
    "汇编指令" 
    : "=&c"(d0), "=&d"(d1), "=&s"(d2)  // 输出操作数
    : "0"(num/8), "q"(num), "1"(to), "2"(from)  // 输入操作数
    : "memory"  // 可能会改变内存内容
);
"=&c"(d0) - 使用ECX寄存器，约束符&表示早期破坏，执行前不与输入共用‌
"=&D"(d1) - 使用EDI,RDI寄存器
"=&S"(d2) - 使用ESI,RSI寄存器

"0"(num/8) - 与第0个输出操作数使用相同寄存器(ECX)，值为num/8
"q"(num) - 使用a、b、c、d中任一通用寄存器，值为num‌
"1"(to) - 与第1个输出操作数使用相同寄存器(EDI,RDI,DI)，值为to指针
"2"(from) - 与第2个输出操作数使用相同寄存器(ESI,RSI,SI)，值为from指针
b4 代表第4个操作数 -- 输出有三个操作数 分别为%0,%1,%2,输入有四个操作数 %3,%4,%5,%6
*/

void*   memcpy(void* from,void* to,long num){
    int d0,d1,d2;
    __asm__ __volatile__ ( 
        "cld     \n\t"
        "rep movsq  \n\t"
        "testb $4,%b4   \n\t"
        "je 1f  \n\t"
        "movsl  \n\t"
        "1:\ttestb $2,%b4   \n\t"
        "je 2f  \n\t"
        "movsw  \n\t"
        "2:\ttestb $1,%b4   \n\t"
        "je 3f  \n\t"
        "movsb  \n\t"
        "3:\n\t"
        :"=&c"(d0),"=&D"(d1),"=&S"(d2)
        :"0"(num/8),"q"(num),"1"(to),"2"(from)
        :"memory"
    );
    return to;
}

/*
    cld 修正方向
    repe 比较rsi,rdi里面的内容，一直到cx为0或zf为0
    repe 影响a(ax,eax,rax寄存器)
    "0"(0)--与第0个输出操作使用相同的寄存器，且将寄存器的值初始化为0

*/
int     memcmp(void* first,void* second,long count){
    register int __res;
    __asm__ __volatile__ (
        "cld    \n\t"
        "repe cmpsb     \n\t"
        "je 1f      \n\t"
        "movl   $1, %%eax   \n\t"
        "jl 1f      \n\t"
        "negl   %%eax       \n\t"        
        "1: \n\t"
        :"=a"(__res)
        :"0"(0),"D"(first),"S"(second),"c"(count)
        :
    );
    return __res;
}


void*   memset(void* address,unsigned char c,long count){
    int d0,d1;
    unsigned long tmp = c * 0x0101010101010101UL;
    __asm__ __volatile__ (
        "cld    \n\t"
        "rep stosq  \n\t"
        "testb $4,%b3 \n\t"
        "je 1f  \n\t"
        "stosl  \n\t"
        "1:\ttestb $2,%b3    \n\t"
        "je 2f  \n\t"
        "stosw  \n\t"
        "2:\ttestb $1,%b3   \n\t"
        "je 3f  \n\t"
        "stosb  \n\t"
        "3:     \n\t"
        :"=&c"(d0),"=&D"(d1)
        :"a"(tmp),"q"(count),"0"(count/8),"1"(address)
        :"memory"
    );
    return address;
}

//jne 1b 表示 如果al不是0,则跳转到1的位置(1在后方，所以是1 b(backward))
void*   strcpy(char* dest,char* src){
    __asm__ __volatile__ (
        "cld    \n\t"
        "1:         \n\t"
        "lodsb  \n\t"
        "stosb  \n\t"        
        "testb %%al,%%al     \n\t"
        "jne 1b \n\t"
        :
        :"D"(dest),"S"(src)
        :"memory"
    );
    return dest;
}

//lodsb,stosb,testb,scasb
char*   strncpy(char* dest,char* src,long count){
    __asm__ __volatile__ (
        "cld    \n\t"
        "1:         \n\t"
        "decq   %2 \n\t"
        "lodsb  \n\t"
        "stosb  \n\t"
        "testb %%al,%%al     \n\t"
        "je 2f  \n\t"
        "test %2,%2 \n\t"
        "je 2f  \n\t"
        "jmp 1b     \n\t"
        "2:         \n\t"
        :
        :"D"(dest),"S"(src),"c"(count)
        :"memory"     
    );
    return dest;
}

//感觉之前写的不好，改一下
char*   strcat(char* dest,char* src){
    __asm__ __volatile__(
        "cld        \n\t"        
        "1:         \n\t"     
        "mov %%al,0  \n\t"
        "scasb      \n\t"
        "je   2f    \n\t"
        "incq   %0  \n\t"           
        "jmp    1b  \n\t"
        "2:         \n\t"
        "lodsb  \n\t"
        "stosb  \n\t"        
        "testb %%al,%%al     \n\t"
        "jne 2b \n\t" 
        :
        :"D"(dest),"S"(src)
        :               
    );   
    return dest;
}

//movb 0(%%dil),%%al 可能这句有问题，编译好像不能通过，换种写法
int     strcmp(char* first,char* second){
    register int __res;    
    __asm__ __volatile__(
        "cld        \n\t"
        "1:         \n\t"
        "lodsb      \n\t"
        "scasb      \n\t"
        "jne    2f      \n\t"
        "jmp    1b      \n\t"
        "2:         \n\t"
        "movl   $1, %%eax   \n\t"        
        "jl     3f  \n\t"
        "negl   %%eax       \n\t"
        "3:         \n\t"
        :"=a"(__res)
        :"0"(0),"D"(first),"S"(second)
        :
    );
    return __res;
}

int     strncmp(char* first,char* second,long count){
    register int __res;

    __asm __volatile__(
        "cld            \n\t"
        "1:             \n\t"
        "cmpq       $0,%4   \n\t"
        "je         3f  \n\t"
        "lodsb          \n\t"
        "scasb          \n\t"
        "jne        2f  \n\t"
        "jmp        1b  \n\t"
        "2:             \n\t"
        "movl   $1,%%eax    \n\t"
        "jl     3f \n\t"
        "negl   %%eax       \n\t"
        "3:             \n\t"
        :"=a"(__res)
        :"0"(0),"D"(first),"S"(second),"c"(count)
        :
    );

    return __res;
}

int     strlen(char* src){
     register int __res;

     __asm__ __volatile__ (
        "cld        \n\t"
        "1:         \n\t"
        "lodsb      \n\t"
        "testb      %%al,%%al    \n\t"
        "je         2f  \n\t"
        "incl       %0  \n\t"
        "jmp    1b  \n\t"
        "2:         \n\t"
        :"=a"(__res)
        :"0"(0),"S"(src)
        :        
     );

     return __res;   
}